package org.example.user.statistic.controller;

import com.fasterxml.jackson.core.JsonProcessingException;
import lombok.extern.slf4j.Slf4j;
import org.example.commons.constant.Constants;
import org.example.commons.controller.BaseController;
import org.example.commons.entity.SysHealthRecord;
import org.example.commons.entity.SysMessage;
import org.example.commons.entity.SysUser;
import org.example.commons.enums.HealthStatusEnum;
import org.example.commons.enums.ReadStatusEnum;
import org.example.commons.enums.SendToEnum;
import org.example.commons.exception.CustomException;
import org.example.commons.utils.SortUtils;
import org.example.commons.vo.ResultVO;
import org.example.commons.websoket.MessageHandler;
import org.example.user.manage.form.SysUserSearchForm;
import org.example.user.statistic.dto.SysHealthRecordDTO;
import org.example.user.statistic.form.HealthRecordSearchForm;
import org.example.user.statistic.service.ISysHealthRecordService;
import org.example.user.warning.service.ISysMessageService;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Sort;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;

/**
 * @author bothin
 */
@RestController
@RequestMapping("/api/health/record")
@Slf4j
public class SysHealthRecordController extends BaseController {
    @Autowired
    private ISysHealthRecordService healthRecordService;

    @Autowired
    private ISysMessageService messageService;

    @Autowired
    private MessageHandler messageHandler;

    /**
     * 导出excel
     * @param response
     * @throws IOException
     */
    @GetMapping("/export/excel")
    public void exportExcel(@RequestParam(name = "ids", required = false)  Long[] ids,
                            HttpServletResponse response) throws IOException {
        List<SysHealthRecordDTO> data = null;
        if (ids==null || ids.length==0){
            data = healthRecordService.queryAll();
        }else {
            data = healthRecordService.findByRecordIdIn(ids);
        }
        super.exportExcel(response,data,SysHealthRecordDTO.class,"出入记录数据表");
    }

    @GetMapping("/{id}")
    public ResultVO findOne(@PathVariable("id") Long id) {
        return ResultVO.success(healthRecordService.queryById(id));
    }

    @GetMapping("/adminId")
    public ResultVO findByAdminId(@RequestParam(name = "adminId") Long adminId,
                                  @RequestParam(name = "page", defaultValue = "1") Integer page,
                                  @RequestParam(name = "size", defaultValue = "10") Integer size,
                                  @RequestParam(name = "isAsc", defaultValue = "false") Boolean isAsc,
                                  @RequestParam(name = "field", defaultValue = "recordTime") String field){
        //排序
        Sort sort = SortUtils.getSort(isAsc, field);
        PageRequest pageRequest = PageRequest.of(page - 1, size, sort);
        return ResultVO.success(healthRecordService.findByAdminId(adminId,pageRequest));
    }

    /**
     * 根据住房id查询出入记录
     * @param userId 住户id
     * @param page  页数
     * @param size  每页大小
     * @param isAsc 是否正序排序
     * @param field 排序的字段
     * @return ResultVO
     */
    @GetMapping("/userId")
    public ResultVO findByUserId(@RequestParam(name = "userId") Long userId,
                                  @RequestParam(name = "page", defaultValue = "1") Integer page,
                                  @RequestParam(name = "size", defaultValue = "10") Integer size,
                                  @RequestParam(name = "isAsc", defaultValue = "false") Boolean isAsc,
                                  @RequestParam(name = "field", defaultValue = "recordTime") String field){
        //排序
        Sort sort = SortUtils.getSort(isAsc, field);
        PageRequest pageRequest = PageRequest.of(page - 1, size, sort);
        return ResultVO.success(healthRecordService.findByUserId(userId,pageRequest));
    }


    /**
     * 查询住户列表
     *
     * @param page  页数
     * @param size  每页大小
     * @param isAsc 是否正序排序
     * @param field 排序的字段
     * @return ResultVO
     */
    @GetMapping
    public ResultVO findList(@RequestParam(name = "page", defaultValue = "1") Integer page,
                             @RequestParam(name = "size", defaultValue = "10") Integer size,
                             @RequestParam(name = "isAsc", defaultValue = "false") Boolean isAsc,
                             @RequestParam(name = "field", defaultValue = "recordTime") String field) {
        //排序
        Sort sort = SortUtils.getSort(isAsc, field);
        PageRequest pageRequest = PageRequest.of(page - 1, size, sort);
        return ResultVO.success(healthRecordService.queryAllPage(pageRequest));
    }

    /**
     * 条件查询住户列表
     *
     * @return ResultVO
     */
    @GetMapping("/search")
    public ResultVO SearchList(HealthRecordSearchForm searchForm) {
        PageRequest pageRequest = null;
        if (StringUtils.isEmpty(searchForm.getField())) {
            pageRequest = PageRequest.of(searchForm.getPage() - 1, searchForm.getSize());
        } else {
            //排序
            Sort sort = SortUtils.getSort(searchForm.getIsAsc(),searchForm.getField());
            pageRequest = PageRequest.of(searchForm.getPage() - 1, searchForm.getSize(), sort);
        }
        Page<SysHealthRecordDTO> recordDTOS = healthRecordService.searchList(searchForm, pageRequest);
        return ResultVO.success(recordDTOS);
    }

    /**
     * 保存出入记录
     *
     * @param record 对象
     * @return ResultVO
     */
    @PostMapping
    public ResultVO saveRecord(@RequestBody SysHealthRecordDTO record) {
        return ResultVO.success(healthRecordService.insert(record));
    }

    /**
     *  微信小程序 保存出入记录，然后推送结果给微信小程序用户端
     *
     * @param record 对象
     * @return ResultVO
     */
    @PostMapping("/wx")
    @Transactional
    public ResultVO saveWXRecord(@RequestBody SysHealthRecordDTO record) throws IOException {
        SysHealthRecordDTO saveHealthRecordDTO = healthRecordService.insert(record);
        SysHealthRecordDTO healthRecordDTO = healthRecordService.queryById(saveHealthRecordDTO.getRecordId());

        //推送扫描结果给住户
        HashMap<String, Object> map = new HashMap<>();
        map.put("type","record");
        map.put("data",healthRecordDTO);
        messageHandler.sendMessage(healthRecordDTO.getUserId(), Constants.MAPPER.writeValueAsString(map) );

        //如果扫描结果存在异常情况，则推送警告消息到后台
        boolean isSend = false;
        Float temperature = healthRecordDTO.getTemperature();
        SysMessage message = new SysMessage();
        message.setStatus(ReadStatusEnum.NO.getCode());
        message.setUserName(healthRecordDTO.getUserName());
        message.setUserId(healthRecordDTO.getUserId());

        //体温异常
        if (temperature >= 37.5 || temperature < 36){
            isSend = true;
            if (temperature < 36){
                message.setTitle("体温异常！低于36度");
            }else {
                message.setTitle("体温异常！高于37.5度");
            }
            message.setContent("住户【" + healthRecordDTO.getUserName()
                    + "】于" + healthRecordDTO.getRecordTime()
                    + "在" + healthRecordDTO.getRecordAddress() + healthRecordDTO.getPassStatusMeaning()
                    + "时被检查员 " + healthRecordDTO.getAdminName() +
                    " 检查到体温异常！体温为" + temperature
                    + "℃ 【备注：出入记录编号（" + healthRecordDTO.getRecordId()
                    + "）-> " + healthRecordDTO.getRemarks() + "】");
        }

        if (!isSend && !healthRecordDTO.getHealthStatus().equals(HealthStatusEnum.HEALTH.getCode())){
            //状态异常
            isSend = true;
            message.setTitle("住户健康状态异常");
            message.setContent("住户【" + healthRecordDTO.getUserName()
                    + "】于" + healthRecordDTO.getRecordTime()
                    + "在" + healthRecordDTO.getRecordAddress() + healthRecordDTO.getPassStatusMeaning()
                    + "时被检查员 " + healthRecordDTO.getAdminName() +
                    " 标记为健康状态异常！【备注：出入记录编号（" + healthRecordDTO.getRecordId()
                    + "）-> " + healthRecordDTO.getRemarks() + "】");
        }
        if (isSend){
            message.setSendTo(SendToEnum.BACKEND.getCode());
            SysMessage saveBackMessage = messageService.insert(message);
            //发送给后台
            messageHandler.sendMessage(0L, Constants.MAPPER.writeValueAsString(saveBackMessage));
            //异步任务 30s后发送消息给住户
            Executors.newSingleThreadScheduledExecutor().schedule(() -> {
                SysMessage userMessage = new SysMessage();
                userMessage.setStatus(ReadStatusEnum.NO.getCode());
                userMessage.setUserName(message.getUserName());
                userMessage.setUserId(message.getUserId());
                userMessage.setSendTo(SendToEnum.USER.getCode());
                userMessage.setTitle(message.getTitle());
                userMessage.setContent(message.getContent());

                SysMessage saveUserMessage = messageService.insert(userMessage);
                HashMap<String, Object> messageMap = new HashMap<>();
                messageMap.put("type","message");
                messageMap.put("data",saveUserMessage);
                try {
                    messageHandler.sendMessage(saveUserMessage.getUserId(), Constants.MAPPER.writeValueAsString(messageMap) );
                } catch (IOException e) {
                    throw  new CustomException("系统出错了！JSON序列化异常");
                }
            }, 30, TimeUnit.SECONDS);

        }


        return ResultVO.success();
    }

    /**
     * 更新出入记录
     *
     * @param record 对象
     * @return ResultVO
     */
    @PutMapping
    public ResultVO updateRecord(@RequestBody SysHealthRecordDTO record) {
        return ResultVO.success(healthRecordService.update(record));
    }

    @DeleteMapping
    public ResultVO deleteSysUser(@RequestParam("id") Long id) {
        healthRecordService.deleteById(id);
        return ResultVO.success();
    }

    @Transactional
    @DeleteMapping("/list")
    public ResultVO deleteSysUser(@RequestParam("ids") Long[] ids) {
        for (Long id : ids) {
            healthRecordService.deleteById(id);
        }
        return ResultVO.success();
    }


}
